﻿/*
 XsltDb is powerful XSLT module for DotnetNuke.
 It offers safe database access, SEO-friendly AJAX support,
 visitor interactions, environment integration (dnn properties,
 request, cookie, session and form values), regular expressions, etc.

 Author:
 
    Anton Burtsev
    burtsev@yandex.ru

 Project home page: 
 
    http://xsltdb.codeplex.com
*/

using System;
using System.Collections;
using System.Security.Cryptography;
using System.Net;
using System.Globalization;
using System.Reflection;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Security;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;
using System.Xml.XPath;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using DotNetNuke.Data;
using DotNetNuke.Common;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Host;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security.Membership;
using DotNetNuke.Services.Mail;
using DotNetNuke.Security.Permissions;
using DotNetNuke.Security;
using DotNetNuke.Services.Personalization;
using DotNetNuke.Framework;

namespace Findy.XsltDb
{
    public partial class Helper
    {
        public XPathNavigator requestxml(string name)
        {
            return request_xml(name);
        }
        public XPathNavigator request_xml(string name)
        {
            try
            {
                HttpPostedFile file = HttpContext.Current.Request.Files[name];
                if (file == null || file.FileName.Length == 0)
                    return CreateRootOnlyNavigator();
                XPathDocument doc = new XPathDocument(file.InputStream);
                return doc.CreateNavigator();
            }
            catch (Exception)
            {
                return CreateRootOnlyNavigator(string.Empty);
            }
        }

        public XPathNavigator requeststring(string name)
        {
            return request_string(name);
        }
        public XPathNavigator request_string(string name)
        {
            try
            {
                HttpPostedFile file = HttpContext.Current.Request.Files[name];
                if (file == null || file.FileName.Length == 0)
                    return CreateRootOnlyNavigator();
                XPathDocument doc = new XPathDocument(file.InputStream);
                return doc.CreateNavigator();
            }
            catch (Exception)
            {
                return CreateRootOnlyNavigator();
            }
        }

        public string requestfile(string name)
        {
            return requestfile(name, null);
        }
        public string requestfile(string name, string fn)
        {
            if (fn != null && fn.Length == 0)
                fn = null;

            var file = HttpContext.Current.Request.Files[name];
            if (file == null || file.FileName.Length == 0)
                return "error:file-not-selected";
            string ext = Path.GetExtension(fn == null ? file.FileName : fn).ToLower();
            if ( fn == null )
                fn = ext;

            var extErr = getExtError(ext);
            if (extErr != null)
                return extErr;

            var m = CreateFileManager();
            var path = m.PreparePath(fn);
            var fullPath = m.FullName(path);
            file.SaveAs(fullPath);
            Data.ExecuteNonQuery("Findy_XsltDb_Files_Insert", new object[]{transformer.DnnSettings.P.PortalID, path});
            return path;
        }

        public string persisttmpfile(string tmpguid, string ext)
        {
            if (!ext.StartsWith("."))
                ext = "." + ext;
            string tmpfile = FileMan.MapPath("~/DesktopModules/Xsltdb/tmp/" + tmpguid + ".bin");
            FileMan m = CreateFileManager();
            string persfile = m.PreparePath(ext);
            File.Move(tmpfile, m.FullName(persfile));
            Data.ExecuteNonQuery("Findy_XsltDb_Files_Insert",
                new object[]{transformer.DnnSettings.P.PortalID, persfile});
            return persfile;
        }

        public string requestfolderfile(string name, string folder)
        {
            HttpPostedFile file = HttpContext.Current.Request.Files[name];
            string fn = Path.GetFileName(file.FileName);
            string ext = Path.GetExtension(fn).ToLower();

            string extErr = getExtError(ext);
            if (extErr != null)
                return extErr;

            FileMan m = CreateFileManager();
            string path = Path.Combine(folder, fn);
            string fullPath = m.FullName(path);
            file.SaveAs(fullPath);
            Data.ExecuteNonQuery("Findy_XsltDb_Files_Insert", new object[]{transformer.DnnSettings.P.PortalID, path});

            return path;
        }

        //private void InvalidateExtracted(string dir, List<string> exts)
        //{
        //    foreach (string extracted in Directory.GetFiles(dir))
        //        if (!exts.Contains(Path.GetExtension(extracted).Substring(1).ToLower()))
        //            File.Delete(extracted);
        //    foreach (string extracted_dir in Directory.GetDirectories(dir))
        //        InvalidateExtracted(extracted_dir, exts);
        //}

        public string virtualfile(string path)
        {
            var appPath = HttpContext.Current.Request.ApplicationPath;
            if (appPath.Length > 1 )
                appPath += "/";

            return appPath + FileMan.PathCombine(getFilesRoot(), path).Replace("\\", "/");
        }

        public XPathNavigator xsltdbxml(string path)
        {
            var m = CreateFileManager();
            return new XPathDocument(m.FullName(path)).CreateNavigator();
        }

        public string xsltdbtext(string path)
        {
            return xsltdbtext(path, null);
        }

        public string xsltdbtext(string path, object encoding)
        {
            if (encoding == null) encoding = "utf-8";
            var enc = cast(encoding).ToString();
            int codepage;
            Encoding e;
            e = int.TryParse(enc, out codepage) 
                ? Encoding.GetEncoding(codepage)
                : Encoding.GetEncoding(enc);

            var m = CreateFileManager();
            using ( var reader = new StreamReader(m.FullName(path), e))
                return reader.ReadToEnd();
        }

        public string expandvirtualpath(string path)
        {
            path = path
                .Replace("~~", HttpContext.Current.Request.ApplicationPath + "/" + transformer.DnnSettings.P.HomeDirectory)
                .Replace("~", HttpContext.Current.Request.ApplicationPath);
            return Regex.Replace(path, "/+", "/");
        }

        public string crop(string path, int x, int y, int w, int h)
        {
            FileMan m = CreateFileManager();
            path = m.FullName(path);
            path = ImageTools.CropImage(path, x, y, w, h);
            return FileMan.VirtualFromFull(path);
        }

        public string portalthumbnail(string path, decimal maxWidth, decimal maxHeight)
        {
            PortalController pc = new PortalController();
            string origPath = FileMan.PathCombine(
                pc.GetPortal(transformer.PortalID).HomeDirectoryMapPath,
                path);
            return Globals.ResolveUrl("~/DesktopModules/XsltDb/jpg.aspx?p=1&file=" +
                HttpUtility.UrlDecode(path) +
                "&w=" + maxWidth +
                "&h=" + maxHeight);
        }
        public string thumbnail(string path, decimal maxWidth, decimal maxHeight)
        {
            try
            {
                FileMan m = CreateFileManager();
                string origFile = m.FullName(path);

                return Globals.ResolveUrl("~/DesktopModules/XsltDb/jpg.aspx?file=" +
                    HttpUtility.UrlDecode(path) +
                    "&w=" + maxWidth +
                    "&h=" + maxHeight);
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        public string downloadfile(string url)
        {
            return downloadfile(url, url.Substring(url.LastIndexOf('.')));
        }
        public string downloadfile(string url, string ext)
        {
            string extErr = getExtError(ext);
            if (extErr != null)
                return extErr;

            if (ext[0] != '.')
                ext = "." + ext;

            string root = FileMan.PathCombine(FileMan.AppPath, getFilesRoot());
            FileMan m = CreateFileManager();
            string path = m.PreparePath(ext);
            string fullPath = m.FullName(path);
            WebClient client = new WebClient();
            try
            {
                client.DownloadFile(url, fullPath);
            }
            catch (Exception e)
            {
                return "error:" + e.Message;
            }
            Data.ExecuteNonQuery("Findy_XsltDb_Files_Insert", new object[]{transformer.DnnSettings.P.PortalID, path});

            return path;
        }

        public string download(string url, string path)
        {
            return download(url, path, url.Substring(url.LastIndexOf('.')));
        }
        public string download(string url, string path, string ext)
        {
            string extErr = getExtError(ext);
            if (extErr != null)
                return extErr;

            WebClient client = new WebClient();
            if (ext[0] != '.' )
                ext = "." + ext;

            if (path != null && path.Length == 0)
                path = null;

            string fn = Guid.NewGuid().ToString() + ext;
            string relativePath = path == null ? fn : Path.Combine(path, fn);

            string fullPath;
            bool IsSuper = transformer.Config.IsSuper;

            if (relativePath[0] == ':' && IsSuper)
            {
                fullPath = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, relativePath.Substring(1));
            }
            else
            {
                if (relativePath[0] == ':')
                    relativePath = relativePath.Substring(1);
                fullPath = mappath(relativePath);
            }
                
            string dir = Path.GetDirectoryName(fullPath);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);

            try
            {
                client.DownloadFile(url, fullPath);
            }
            catch (Exception e)
            {
                return "error:" + e.Message;
            }

            return fn;
        }

        public static string CreateThumbnail(string origFile, double x, double y, double w, double h, double px, double py)
        {
            if (!File.Exists(origFile))
                return "";

            string key = "k" + x + "|" + y + "|" + w + "|" + h + "|" + px + "|" + py;
            string fnPart = Math.Abs(key.GetHashCode()).ToString();

            string thumbDir = origFile + ".thumb";
            string thumbPath = thumbDir + "\\" + fnPart + Path.GetExtension(origFile);
            if (!File.Exists(thumbPath))
            {
                lock (typeof(Helper))
                {
                    System.Drawing.Image original;
                    using (FileStream fr = File.OpenRead(origFile))
                        original = System.Drawing.Image.FromStream(fr);
                    Rectangle sourceRect = new Rectangle(
                        (int)(original.Width * x),
                        (int)(original.Height * y),
                        (int)(original.Width * w),
                        (int)(original.Height * h));

                    int PX = ((int)(px * original.Width)) - sourceRect.Left-1;
                    int PY = ((int)(py * original.Height)) - sourceRect.Top-1;

                    Bitmap bmp = new Bitmap(sourceRect.Width, sourceRect.Height);
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.SmoothingMode = SmoothingMode.AntiAlias;
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                        g.DrawImage(original,
                            new Rectangle(0, 0, sourceRect.Width, sourceRect.Height),
                            sourceRect,
                            GraphicsUnit.Pixel);

                        using (Pen p = new Pen(Color.FromArgb(128, 255, 0, 0), 15))
                        {
                            p.StartCap = LineCap.Round;
                            p.EndCap = LineCap.ArrowAnchor;

                            g.DrawLine(p, 10, 10, PX, PY);
                        }
                    }
                    if (!Directory.Exists(thumbDir))
                        Directory.CreateDirectory(thumbDir);
                    using (FileStream fs = File.Create(thumbPath))
                        bmp.Save(fs, ImageFormat.Jpeg);
                }
            }

            return thumbPath;
        }

        public static byte[] CreateThumbnail(string origFile, decimal maxWidth, decimal maxHeight, PointF[] arrows)
        {
            return CreateThumbnail(origFile, maxWidth, maxHeight, arrows, null);
        }
        public static byte[] CreateThumbnail(string origFile, decimal maxWidth, decimal maxHeight, PointF[] arrows, string Breaker)
        {
            if (!File.Exists(origFile))
                return null;

            ImageTools.ThumbnailArgs args = new ImageTools.ThumbnailArgs();
            args.OriginalPath = origFile;
            args.Width = maxWidth;
            args.Height = maxHeight;
            args.IsPersistent = !string.IsNullOrEmpty(Breaker);
            args.Breaker = Breaker;
            args.customDraw = delegate(Graphics g, Bitmap original, ImageTools.ThumbnailArgs a)
            {
                decimal k = Math.Min(a.Height / original.Height, a.Width / original.Width);
                int rWidth = (int)Math.Round(k * original.Width);
                int rHeight = (int)Math.Round(k * original.Height);

                int alpha = k < 0.5m ? 255 : 128;
                using (SolidBrush b = new SolidBrush(Color.FromArgb(alpha, 255, 0, 0)))
                {
                    using (Pen p = new Pen(b, (float)(13 * k + 3)))
                    {
                        foreach (PointF point in arrows)
                        {
                            p.StartCap = LineCap.Round;
                            p.EndCap = LineCap.ArrowAnchor;
                            float delta_x = point.X > 0.15f ? -0.1f : 0.1f;
                            float delta_y = point.Y > 0.15f ? -0.03f : 0.03f;
                            int x1 = (int)((point.X + delta_x) * rWidth);
                            int x2 = (int)(point.X * rWidth);
                            int y1 = (int)((point.Y + delta_y) * rHeight);
                            int y2 = (int)(point.Y * rHeight);

                            g.DrawLine(p, x1, y1, x2, y2);
                        }
                    }
                }
            };

            return ImageTools.CreateThumbnail(args).ThumbnailBytes;
        }

        public string resx(string path, string key)
        {
            return XsltDbResX.GetString(path, culture(), transformer.PortalID, key);
        }
        public XPathNavigator files(string path)
        {
            FileMan m = CreateFileManager();
            return BuildFilesList(m.FullName(path));
        }

        public XPathNavigator portalfile(int FileID)
        {
            DotNetNuke.Services.FileSystem.FileController fc = new DotNetNuke.Services.FileSystem.FileController();
            DotNetNuke.Services.FileSystem.FileInfo fi = fc.GetFileById(FileID, transformer.PortalID);
            if (fi == null)
                return CreateRootOnlyNavigator("File " + FileID + " not found");

            XmlDocument doc = new XmlDocument();
            XmlElement root = doc.CreateElement("root");
            string PortalHome = new PortalController().GetPortal(transformer.PortalID).HomeDirectory;
            doc.AppendChild(root);
            insertElem(doc, "virtual", "/" + PortalHome + "/" + fi.RelativePath);
            insertElem(doc, "relative", fi.RelativePath);
            insertElem(doc, "physical", fi.PhysicalPath);
            insertElem(doc, "height", fi.Height.ToString());
            insertElem(doc, "width", fi.Width.ToString());
            insertElem(doc, "size", fi.Size.ToString());
            return doc.CreateNavigator();
        }
        private static void insertElem(XmlDocument doc, string name, string value)
        {
            XmlElement e = doc.CreateElement(name);
            e.InnerText = value;
            doc.DocumentElement.AppendChild(e);
        }
        public string portalfilephysicalpath(int FileID)
        {
            DotNetNuke.Services.FileSystem.FileController fc = new DotNetNuke.Services.FileSystem.FileController();
            return fc.GetFileById(FileID, transformer.PortalID).PhysicalPath;
        }

        public XPathNavigator portalfiles()
        {
            return portalfiles(null);
        }
        public XPathNavigator portalfiles(string path)
        {
            return BuildFilesList(FileMan.PathCombine(FileMan.AppPath, getPortalHome(transformer.PortalID), path ?? ""));
        }

        private XPathNavigator BuildFilesList(string origDir)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<root>");
            if (Directory.Exists(origDir))
            {
                DirectoryInfo dirInfo = new DirectoryInfo(origDir);
                FileSystemInfo[] items = dirInfo.GetFileSystemInfos();
                foreach (FileSystemInfo fsi in items)
                {
                    FileInfo fi = fsi as FileInfo;
                    if (fi != null) sb.AppendFormat("<file size=\"{0}\">{1}</file>", fi.Length, HttpUtility.HtmlEncode(fi.Name));
                    else sb.AppendFormat("<dir>{0}</dir>", fsi.Name);
                }
            }
            sb.Append("</root>");

            return CreateNavigator(sb.ToString());
        }

        public string deleteportalfile(string path)
        {
            try
            {
                string fullpath = Path.Combine(transformer.DnnSettings.P.HomeDirectoryMapPath, path);
                if (File.Exists(fullpath))
                    File.Delete(fullpath);
                return "ok";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        public XPathNavigator readportalxml(string path)
        {
            string fullpath = Path.Combine(transformer.DnnSettings.P.HomeDirectoryMapPath, path);

            XPathDocument doc = new XPathDocument("file:///" + fullpath);
            return doc.CreateNavigator();
        }

        public string readfile(string path)
        {
            return readfile(path, "utf-8");
        }
        public string readfile(string path, string encoding)
        {
            try
            {
                FileMan m = CreateFileManager();
                using (StreamReader sr = new StreamReader(m.FullName(path), Encoding.GetEncoding(encoding)))
                {
                    return sr.ReadToEnd();
                }
            }
            catch (Exception)
            {
                return "";
            }
        }

        public XPathNavigator readxml(string path)
        {
            try
            {
                FileMan m = CreateFileManager();
                XPathDocument doc = new XPathDocument("file:///" + m.FullName(path));
                return doc.CreateNavigator();
            }
            catch (Exception ex)
            {
                return CreateRootOnlyNavigator(ex.Message);
            }
        }

        // read-portal-tabbed-txt
        public XPathNavigator readportaltabbedtxt(string path)
        {
            return readportaltabbedtxt(path, string.Empty);
        }
        public XPathNavigator readportaltabbedtxt(string path, string tags)
        {
            return readportaltabbedtxt(path, tags, "utf-8");
        }
        static Regex unescapeRegex = new Regex(@"(\\\\|\\n|\\t|\\r)");
        public XPathNavigator readportaltabbedtxt(string path, string tags, string encoding)
        {
            try
            {
                string[] names = tags.Split(',');

                for (int i = 0; i < names.Length; i++)
                    names[i] = names[i].Trim();

                string fullpath = Path.Combine(transformer.DnnSettings.P.HomeDirectoryMapPath, path);
                return ReadTabbedFile(encoding, names, fullpath);
            }
            catch (Exception ex)
            {
                return CreateRootOnlyNavigator(ex.Message);
            }
        }

        public XPathNavigator readtabbedtxt(string path)
        {
            return readtabbedtxt(path, string.Empty);
        }
        public XPathNavigator readtabbedtxt(string path, string tags)
        {
            return readtabbedtxt(path, tags, "utf-8");
        }

        public XPathNavigator readtabbedtxt(string path, string tags, string encoding)
        {
            try
            {
                string[] names = tags.Split(',');

                for (int i = 0; i < names.Length; i++)
                    names[i] = names[i].Trim();

                FileMan m = CreateFileManager();
                string fullpath = m.FullName(path);
                return ReadTabbedFile(encoding, names, fullpath);
            }
            catch (Exception ex)
            {
                return CreateRootOnlyNavigator(ex.Message);
            }
        }

        
        private static XPathNavigator ReadTabbedFile(string encoding, string[] names, string fullpath)
        {
            using (StreamReader sr = new StreamReader(fullpath, Encoding.GetEncoding(encoding)))
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml("<root/>");

                while (sr.Peek() >= 0)
                {
                    XmlElement row = doc.CreateElement("row");
                    string line = sr.ReadLine();
                    string[] values = line.Split('\t');
                    for (int i = 0; i < values.Length; i++)
                    {
                        string val = values[i];
                        val = unescapeRegex.Replace(val, delegate(Match m)
                        {
                            string s = m.Value;
                            switch (s)
                            {
                                case @"\\": return "\\";
                                case @"\n": return "\n";
                                case @"\r": return "\r";
                                case @"\t": return "\t";
                                default: return s;
                            }
                        });

                        string tag = i < names.Length && names[i].Length > 0 ? names[i] : "column-" + i;
                        XmlElement e = doc.CreateElement(tag);
                        e.InnerText = val;
                        row.AppendChild(e);
                    }
                    doc.DocumentElement.AppendChild(row);
                }
                return new XPathDocument(new StringReader(doc.OuterXml)).CreateNavigator();
            }
        }

        public int writefile(string content, string path, string encoding)
        {
            try
            {
                FileMan m = CreateFileManager();
                using (StreamWriter sw = new StreamWriter(m.FullName(path), false, Encoding.GetEncoding(encoding)))
                {
                    sw.Write(content);
                    return 0;
                }
            }
            catch (Exception)
            {
                return 1;
            }
        }

        public int writefile(string content, string path)
        {
            return writefile(content, path, "utf-8");
        }

        public string mail(string from, string to, string subject, string body)
        {
            return Mail.SendMail(
                from, to, "", "", "", MailPriority.Normal,
                subject, MailFormat.Html, Encoding.UTF8, body,
                new string[]{}, "", "", "", "", false);
        }

        public int userid(string login, string password)
        {
            var status = new UserLoginStatus();
            var ui = UserController.ValidateUser(
                transformer.PortalID,
                login, password, "", "", "", ref status);

            if (ui == null)
                return -1;

            return ui.UserID;
        }

        public string login(string username, string password)
        {
            return login(username, password, false);
        }
        public string login(string username, string password, bool remember)
        {
            var status = new UserLoginStatus();
            var ui = UserController.ValidateUser(transformer.PortalID, username, password, "", "", HttpContext.Current.Request.UserHostAddress, ref status);
            if (status == UserLoginStatus.LOGIN_SUPERUSER)
                status = UserLoginStatus.LOGIN_SUCCESS;
            if ( status == UserLoginStatus.LOGIN_SUCCESS && ui != null )
                UserController.UserLogin(transformer.PortalID, ui, "", HttpContext.Current.Request.UserHostAddress, remember);
            return status.ToString();
        }

        public bool logout()
        {
            if ( HttpContext.Current.Session != null )
                HttpContext.Current.Session.Abandon();
            FormsAuthentication.SignOut();
            return true;
        }

        public string password(int UserID)
        {
            return password(UserID, string.Empty);
        }
        public string password(int UserID, string passwordAnswer)
        {
            try
            {
                UserInfo ui = UserController.GetUserById(transformer.PortalID, UserID);
                return UserController.GetPassword(ref ui, passwordAnswer);
            }
            catch (Exception) { return string.Empty; }
        }

        public string createuser(string email, string password, string displayName, string phone)
        {
            return createuser(email, password, displayName, phone, true);
        }
        public string createuser(string email, string password, string displayName, string phone, bool auth)
        {
            string username = email;
            email = Regex.Replace(email, "#.*", string.Empty);
            UserInfo ui = new UserInfo();
            ui.PortalID = transformer.PortalID;
            ui.Username = username;
            ui.Email = email;
            ui.DisplayName = displayName;
            ui.Profile.Telephone = phone;
            ui.Membership.Password = password;
            ui.Membership.Approved = auth;
            UserCreateStatus ucs = UserController.CreateUser(ref ui);
            return ucs.ToString();
        }

        public string createuser(XPathNavigator profile)
        {
            profile = profile.SelectSingleNode("//profile");
            string email = profile.Value("@email");
            string login = profile.Value("@login");
            if (string.IsNullOrEmpty(login))
                login = email;
            bool separatePortal = profile.Value("@separate").ToLower() == "true";

            if (separatePortal)
                login += "#" + transformer.PortalID;

            UserInfo ui = new UserInfo();
            ui.PortalID = transformer.PortalID;

            ui.Username = login;
            ui.Email = email;
            ui.DisplayName = profile.Value("@display-name");
            ui.Profile.Telephone = profile.Value("@phone");
            ui.Membership.Password = profile.Value("@password");
            ui.Membership.Approved = profile.Value("@approved").ToLower() == "true";
            UserCreateStatus ucs = UserController.CreateUser(ref ui);
            return ucs.ToString();
        }

        public string updateuser(int UserID, string displayName, string phone)
        {
            var ui = UserController.GetUserById(transformer.PortalID, UserID);
            ui.DisplayName = displayName;
            ui.Profile.Telephone = phone;

            UserController.UpdateUser(transformer.PortalID, ui);

            return string.Empty;
        }

        public string updateuser(int UserID, string displayName, string phone, string email)
        {
            var ui = UserController.GetUserById(transformer.PortalID, UserID);
            ui.DisplayName = displayName;
            ui.Profile.Telephone = phone;
            ui.Email = email;

            UserController.UpdateUser(transformer.PortalID, ui);

            return string.Empty;
        }

        public bool changepassword(int UserID, string oldPassword, string newPassword)
        {
            try
            {
                var ui = UserController.GetUserById(transformer.PortalID, UserID);
                return UserController.ChangePassword(ui, oldPassword, newPassword);
            }
            catch (Exception) { }
            return false;
        }

        public string createactivationlink(string login)
        {
            var guid = Data.ExecuteSQLScalar("select UserId from aspnet_Users where UserName = @username",
                                             new[] {new SqlParameter("@username", login)});

            if (guid == null) return "user-not-found";

            var url = HttpContext.Current.Request.Url;

            return url.Scheme + "://" + url.Host + ":" + url.Port +
                   VirtualPathUtility.ToAbsolute("~/DesktopModules/XsltDb/ActivateUser.ashx") +
                   "?code=" + guid;
        }

        private Dictionary<string, object> variables = new Dictionary<string,object>();
        public object var(string name, object value)
        {
            object oldval = null;
            variables.TryGetValue(name, out oldval);
            if ( value != null )
                variables[name] = value;
            return oldval ?? "";
        }

        public object var(string name)
        {
            return var(name, null);
        }

        public string urlencode(string str)
        {
            return HttpContext.Current.Server.UrlEncode(str);
        }
        public string urlencodeunicode(string str)
        {
            return HttpUtility.UrlEncodeUnicode(str).Replace("+", "%u0020");
        }

        public string urldecode(string str)
        {
            return HttpContext.Current.Server.UrlDecode(str);
        }

        static Regex UrlDecodeRegex = new Regex("%..|%u....|\\+", RegexOptions.Singleline | RegexOptions.Compiled);
        public string urldecode(string str, string encoding)
        {
            Encoding enc = Encoding.GetEncoding(encoding);
            return UrlDecodeRegex.Replace(str, delegate(Match m) {
                try
                {
                    if (m.Value.Length == 3)
                        return enc.GetString(new byte[] { byte.Parse(m.Value.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier) });
                    if (m.Value.Length == 6)
                        return ((char)uint.Parse(m.Value.Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier)).ToString();
                    if (m.Value == "+") return " ";
                }
                catch (Exception) { }
                return string.Empty;
            });
        }

        private static Regex DateTimeRegex = new Regex(@"^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(\+\d\d:\d\d)?$", RegexOptions.Compiled);
        private object ensureDateTime(object obj)
        {
            obj = cast(obj);
            string str = obj as string;
            if (str != null && str.Length > 0 && char.IsDigit(str[0]) && DateTimeRegex.IsMatch(str))
                obj = DateTime.Parse(str, CultureInfo.InvariantCulture);
            return obj;
        }
        public string jsencode(object s)
        {
            return Transformer.EncodeJsString(ensureDateTime(s), true);
        }
        public string jencode(object s)
        {
            return Transformer.EncodeJsString(ensureDateTime(s), false);
        }

        public string md5(string input)
        {
            return input.MD5();
        }

        public string cookie()
        {
            bool first = true;
            StringBuilder sb = new StringBuilder();
            foreach (HttpCookie c in HttpContext.Current.Request.Cookies)
            {
                if (!first)
                    sb.Append("&");
                sb.Append(HttpUtility.UrlEncode(c.Name) + "=" + HttpUtility.UrlEncode(c.Value));
                first = false;
            }
            return sb.ToString();
        }
        public object cookie(string name)
        {
            return cookie(name, string.Empty);
        }

        public object cookie(string name, object dflt)
        {
            HttpCookie c = HttpContext.Current.Request.Cookies[name];
            if (c == null)
                return dflt;
            return c.Value;
        }

        public object setcookie(string name, string value)
        {
            return setcookie(name, value, null);
        }

        public object setcookie(string name, string value, string expires)
        {
            HttpCookie c = new HttpCookie(name, value);
            if (expires == "delete")
                c.Expires = DateTime.Now.AddYears(-10);
            DateTime dtExpires;
            if (expires != null && expires.Length > 0 && DateTime.TryParse(expires, out dtExpires))
                c.Expires = dtExpires;

            HttpContext.Current.Response.Cookies.Add(c);

            return cookie(name);
        }
        public string cancelcookie(string name)
        {
            HttpCookie c = new HttpCookie(name, "delete");
            c.Expires = DateTime.Now.AddYears(-10);
            HttpContext.Current.Response.Cookies.Add(c);
            return "";
        }

        static Regex fieldregex = new Regex(@"^\d+\:", RegexOptions.Singleline | RegexOptions.Compiled);
        private static string GetDelim(string format)
        {
            Match m = fieldregex.Match(format);
            if (m.Success && m.Index == 0)
                return ",";
            else if (!format.StartsWith(":"))
                return ":";
            return "";
        }

        public string newid() { return Guid.NewGuid().ToString(); }

        public object formatdate(object date) { return fmtdate(date, string.Empty); }
        public object formatdate(object date, string format) { return fmtdate(date, format); }
        public object formatdate(object date, string format, string inFormat) { return fmtdate(date, format, inFormat); }
        public object fmtdate(object date) { return fmtdate(date, string.Empty); }
        public object fmtdate(object date, string format) { return fmtdate(date, format, string.Empty); }
        public object fmtdate(object date, string format, string inFormat)
        {
            try
            {
                object trueDate = cast(date);
                DateTime typifiedDate;
                if (!(trueDate is DateTime))
                {
                    if (trueDate.ToString().Trim().Length == 0)
                        return string.Empty;
                    if (inFormat.Trim().Length == 0)
                        typifiedDate = Convert.ToDateTime(trueDate);
                    else
                        typifiedDate = DateTime.ParseExact(trueDate.ToString().Trim(), inFormat,
                            System.Globalization.CultureInfo.InvariantCulture);
                }
                else
                    typifiedDate = (DateTime)trueDate;

                format = format.Trim();
                if (format.Length == 0 || format.ToLower() == "pure")
                    return typifiedDate;

                return string.Format(
                    "{0" + GetDelim(format) + format + "}",
                    typifiedDate);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        public object formatnumber(object num) { return fmtnumber(num, string.Empty); }
        public object formatnumber(object num, string format) { return fmtnumber(num, format); }
        public object fmtnumber(object num) { return fmtnumber(num, string.Empty); }
        public object fmtnumber(object num, string format)
        {
            try
            {
                object trueNum = cast(num);
                if (trueNum.ToString().Trim().Length == 0)
                    return string.Empty;

                decimal val;
                if (trueNum is decimal)
                    val = (decimal)num;
                else
                {
                    string trueStringNum = trueNum.ToString().Replace(",", ".");
                    val = Decimal.Parse(trueStringNum,
                        NumberStyles.Number | NumberStyles.AllowExponent,
                        CultureInfo.InvariantCulture);
                }

                format = format.Trim();
                if (format.Length == 0 || format.ToLower() == "pure")
                    return val;

                return string.Format("{0" + GetDelim(format) + format + "}", val);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        public string lower(string s)
        {
            return s.ToLower();
        }
        public string upper(string s)
        {
            return s.ToUpper();
        }

        public int indexof(string source, string pattern)
        {
            Regex r = new Regex(pattern, RegexOptions.Singleline);
            Match m = r.Match(source);
            if (m.Success)
                return m.Index;
            return -1;
        }

        public string replace(string source, string pattern, string replacer)
        {
            Regex r = new Regex(pattern, RegexOptions.Singleline);
            return r.Replace(source, replacer);
        }

        public string regexencode(string input)
        {
            const string regexchars = @"\^.+*?[](){}|";
            Regex r1 = new Regex(".");
            string group = r1.Replace(regexchars, "|\\$0");
            group = "(" + group.Substring(1) + ")";

            Regex r2 = new Regex(group);
            return r2.Replace(input, "\\$0");
        }

        public string htmlencode(string s)
        {
            return HttpUtility.HtmlEncode(s);
        }
        public string htmlattributeencode(string s)
        {
            return HttpUtility.HtmlAttributeEncode(s);
        }
        public string htmldecode(string s)
        {
            return HttpUtility.HtmlDecode(s);
        }

        public object editortext(string id)
        {
            return editortext(id, string.Empty);
        }

        static Regex tryUrl = new Regex("%3c|%3e", RegexOptions.Singleline | RegexOptions.Compiled);
        static Regex tryHtml = new Regex("&lt;|&gt;", RegexOptions.Singleline | RegexOptions.Compiled);
        public object editortext(string id, object dflt)
        {
            string editorName = clientname(id) + "$" + id;
            string text = request(editorName, dflt).ToString();
            if ( text.Length == 0)
                return dflt;
            try
            {
                if (tryUrl.Matches(text).Count >= tryHtml.Matches(text).Count)
                    return urldecode(text);
                return htmldecode(text);
            }
            catch (Exception)
            {
                return text;
            }
        }

        public string clientid() { return clientid(string.Empty); }
        public string clientid(string id)
        {
            if (id.Length > 0) id = "_" + id;
            return Transformer.TrueHost.ClientID + id;
        }

        public string clientname() { return clientname(string.Empty); }
        public string clientname(string id)
        {
            if (id.Length > 0) id = "$" + id;
            return Transformer.TrueHost.UniqueID + id;
        }

        public DateTime date()
        {
            return DateTime.Now;
        }

        public object date(string format)
        {
            return fmtdate(date(), format);
        }

        public bool today(DateTime date)
        {
            return date.Date == DateTime.Today;
        }

        public string transform(string xml, string xsl)
        {
            return this.transformer.JustTransform(xsl, xml, false, false);
        }

        public string xsltdb(string alias)
        {
            return xsltdb(alias, "<root/>");
        }
        public string xsltdb(string alias, string xml)
        {
            XsltDbUtils.aConfig c = XsltDbUtils.GetConfigByService(alias);
            if (c == null)
                return string.Empty;
            return transform(xml, c.ActiveXslt);
        }

        public string applytemplate(string template, string name, object xml)
        {
            string data = ObjectToText(xml, true);
            return transformer.ApplyTemplate(template, name, data);
        }

        public string test_with_delay(int delay)
        {
            System.Threading.Thread.Sleep(delay);
            return DateTime.Now.ToString();
        }

        public int delay(int delay)
        {
            System.Threading.Thread.Sleep(delay);
            return 0;
        }

        public XPathNavigator portalimagesize(string path)
        {
            string fullPath = FileMan.PathCombine(PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath, path);
            return getImageSize(fullPath);
        }
        public XPathNavigator imagesize(string path)
        {
            FileMan m = CreateFileManager();
            return getImageSize(m.FullName(path));
        }
        private static XPathNavigator getImageSize(string fullPath)
        {
            string full = fullPath.ToLower();
            string ext = Path.GetExtension(full);
            if ( ! ".jpg.jpeg.gif.tif.tiff.bmp.png.swf.flv".Contains(ext) )
                return CreateNavigator("<root>Unsupported image format</root>");

            bool done = false;
            int width = 0, height = 0;
            long length = 0;
            if(File.Exists(full)){

              FileInfo fi = new FileInfo(full);
              length = fi.Length;
              if (full.EndsWith(".jpg") || full.EndsWith(".jpeg"))
                done = ImageTools.GetJpegDimension(full, out width, out height);

              if (full.EndsWith(".flv"))
                done = ImageTools.GetFlvDimension(full, out width, out height);

              if (full.EndsWith(".swf"))
                done = ImageTools.GetSwfDimension(full, out width, out height);

              if (!done)
              {
                using (FileStream fs = File.OpenRead(full))
                {
                    System.Drawing.Image i = System.Drawing.Image.FromStream(fs);
                    width = i.Size.Width;
                    height = i.Size.Height;

                }
              }
            }
            return CreateNavigator("<root><width>" + width + "</width><height>" + height + "</height><length>" + length + "</length></root>");
        }

        public long filesize(string path)
        {
            FileMan m = CreateFileManager();
            string full = m.FullName(path);
            if (!File.Exists(full))
                return -1;
            FileInfo fi = new FileInfo(full);
            return fi.Length;
        }

        private static object cast(object val)
        {
            if (val is XPathNodeIterator)
            {
                XPathNodeIterator iterator = (XPathNodeIterator)val;
                StringBuilder sb = new StringBuilder();
                if (iterator.MoveNext())
                    val = iterator.Current.Value;
                else
                    val = string.Empty;
            }
            if (val is XPathNavigator)
                val = (val as XPathNavigator).Value;

            return val;
        }

        public bool isajax() { return transformer.IsAjax; }
        public bool issubmit() { return transformer.IsPostBack; }
        public bool isnavigate() { return transformer.IsNavigate; }

        public string culture()
        {
            return System.Threading.Thread.CurrentThread.CurrentCulture.ToString();
        }

        public object gettabsetting(string key)
        {
            return gettabsetting(key, string.Empty);
        }
        public object gettabsetting(string key, object dflt)
        {
            TabController tc = new TabController();

            MethodInfo mi = tc.GetType().GetMethod("GetTabSettings", new Type[] { typeof(int) });
            Hashtable h = (Hashtable)mi.Invoke(tc, new object[] { Transformer.TabID });
            object val = h[key];
            if (val == null || val.ToString().Trim().Length == 0)
                return dflt;
            return val;
        }

        public object settabsetting(string key, string val)
        {
            TabController tc = new TabController();
            MethodInfo mi = tc.GetType().GetMethod("UpdateTabSetting", new Type[] { typeof(int), typeof(string), typeof(string), });
            mi.Invoke(tc, new object[] { Transformer.TabID, key, val });
            return true;
        }

        public object getmodulesetting(string key)
        {
            return getmodulesetting(key, string.Empty);
        }
        public object getmodulesetting(string key, object dflt)
        {
            Hashtable t = (Hashtable)HttpContext.Current.Items["TempModuleSettings"];
            if (t != null)
            {
                if (t[key] == null || t[key].ToString().Trim().Length == 0)
                    return dflt;
                return t[key].ToString();
            }
            ModuleController mc = new ModuleController();

            object val = mc.GetModuleSettings(Transformer.ModuleID)[key];
            if (val == null || val.ToString().Trim().Length == 0)
                return dflt;
            return val;
        }
        public bool setmodulesetting(string key, string val)
        {
            ModuleController mc = new ModuleController();
            mc.UpdateModuleSetting(Transformer.ModuleID, key, val);
            return true;
        }
        public object gettabmodulesetting(string key)
        {
            return gettabmodulesetting(key, string.Empty);
        }
        public object gettabmodulesetting(string key, object dflt)
        {
            ModuleController mc = new ModuleController();
            object val = mc.GetTabModuleSettings(Transformer.TabModuleID)[key];
            if (val == null || val.ToString().Trim().Length == 0)
                return dflt;
            return val;
        }
        public bool settabmodulesetting(string key, string val)
        {
            ModuleController mc = new ModuleController();
            mc.UpdateTabModuleSetting(Transformer.TabModuleID, key, val);
            return true;
        }

        public string dnnobjectqualifier()
        {
            return DataProvider.Instance().ObjectQualifier;
        }
        public string dnndatabaseowner()
        {
            return DataProvider.Instance().DatabaseOwner;
        }

        public string dnnpreparesql(string sql)
        {
            return sql
                .Replace("{databaseOwner}", DataProvider.Instance().DatabaseOwner)
                .Replace("{objectQualifier}", DataProvider.Instance().ObjectQualifier);
        }

        public string eventsource()
        {
            return eventsource(false);
        }
        public string pagevalidate()
        {
            return pagevalidate(null);
        }
        public string pagevalidate(string group)
        {
            if (HttpContext.Current.Handler is System.Web.UI.Page)
            {
                System.Web.UI.Page p = (System.Web.UI.Page)HttpContext.Current.Handler;
                if (!string.IsNullOrEmpty(group))
                    p.Validate();
                else
                    p.Validate(group);
            }
            return string.Empty;
        }
        public string eventsourcefull()
        {
            return eventsource(true);
        }
        public string eventsource(bool full)
        {
            Type t = typeof(System.Web.UI.Page);

            FieldInfo fi = t.GetField("_registeredControlThatRequireRaiseEvent", BindingFlags.NonPublic | BindingFlags.Instance);

            object v = fi.GetValue(HttpContext.Current.Handler);

            if (v != null)
            {
                Control c = (System.Web.UI.Control)v;
                return full ? c.UniqueID : c.ID;
            }
            
            return string.Empty;
        }

        public string resolveurl(string relative)
        {
            return Globals.ResolveUrl(relative);
        }

        public string xsltdbcontext()
        {
            IXsltDbHost host = (IXsltDbHost)transformer.TrueHost;
            if ( host != null )
                return host.XContext;
            return string.Empty;
        }

        public string serviceurl(string serviceName)
        {
            string ws = Globals.ResolveUrl("~/DesktopModules/XsltDb/ws.ashx");
            return
                 ws + "?service=" + urlencodeunicode(HttpUtility.HtmlDecode(serviceName)) +
                 "&config=" + (transformer.Config != null ? transformer.Config.ConfigID : string.Empty) +
                "&mod=" + transformer.ModuleID +
                "&tabid=" + transformer.TabID +
                "&tmid=" + transformer.TabModuleID;
        }
        public int clearxsltdbportalsettingscache(string key)
        {
            StaticCache2.Remove(XsltDbUtils.settings_slot);
            return 0;
        }

        public string skinpath()
        {
            PageBase pb = HttpContext.Current.Handler as PageBase;
            if (pb != null)
                return DotNetNuke.UI.Skins.Skin.GetSkin(pb).SkinPath;
            else
                return request("XsltDb_SkinPath").ToString();
        }

        public string tolower(string str)
        {
            return str.ToLower();
        }
        public string toupper(string str)
        {
            return str.ToUpper();
        }

        public bool setupoutputcache(int seconds)
        {
            return setupoutputcache(seconds, null);
        }
        public bool setupoutputcache(int seconds, string location)
        {
            HttpCacheability ca = HttpCacheability.ServerAndPrivate;

            if (!string.IsNullOrEmpty(location))
                ca = (HttpCacheability)Enum.Parse(typeof(HttpCacheability), location);

            if (transformer.UserID > 0)
                seconds = 0;

            HttpContext.Current.Response.Cache.SetLastModified(HttpContext.Current.Timestamp);
            HttpContext.Current.Response.Cache.SetExpires(HttpContext.Current.Timestamp.AddSeconds(seconds));
            HttpContext.Current.Response.Cache.SetCacheability(ca);
            HttpContext.Current.Response.Cache.SetValidUntilExpires(true);
            HttpContext.Current.Response.Cache.SetMaxAge(TimeSpan.FromSeconds(seconds));
            HttpContext.Current.Response.Cache.SetVaryByCustom("XsltDbStar");
            HttpContext.Current.Response.Cache.VaryByParams.IgnoreParams = true;

            return true;
        }

        public bool iseditable()
        {
            var mi = transformer.DnnSettings.M;
            if (mi == null) return false; // XsltDb as a UserControl has no module context

            if (issuperuser()) return true;

            var editPerm = ModulePermissionController.HasModuleAccess(
                SecurityAccessLevel.Edit, "CONTENT", mi);
            if (editPerm)
            {
                var setting = Convert.ToString(Personalization.GetProfile("Usability",
                    "UserMode" + transformer.PortalID.ToString()));
                return setting.ToUpper() == "EDIT";
            }
            return false;
        }

        public bool addcounter(string objectCode, string counterType)
        {
            const string key = "xsltdb:super-fast-counters";
            lock(typeof(Helper))
            {
                var counters = (DataTable) StaticCache2.Get(key, () =>
                                                                     {
                                                                         var dt = new DataTable("couters");
                                                                         dt.Columns.Add("PortalID", typeof (int));
                                                                         dt.Columns.Add("ObjectCode", typeof (string));
                                                                         dt.Columns.Add("CounterType", typeof (string));
                                                                         dt.Columns.Add("EventDate", typeof (DateTime));
                                                                         dt.Columns.Add("UserIP", typeof (string));

                                                                         dt.ExtendedProperties.Add("Created", DateTime.Now);

                                                                         return dt;
                                                                     });
                counters.Rows.Add(new object[]
                                      {
                                          transformer.PortalID,
                                          objectCode,
                                          counterType,
                                          DateTime.Now,
                                          HttpContext.Current.Request.UserHostAddress
                                      });
                var created = (DateTime) counters.ExtendedProperties["Created"];
                if ( created.AddSeconds(5) < DateTime.Now )
                {
                    const string sql = "exec {databaseOwner}[{objectQualifier}Findy_XsltDb_FlushCounters] @Counters";
                    StaticCache2.Remove(key);

                    new Thread(delegate()
                                   {
                                       Data.ExecuteSQLCommand(sql, new[]
                                                                       {
                                                                           new SqlParameter
                                                                               {
                                                                                   SqlDbType = SqlDbType.Structured,
                                                                                   ParameterName = "@Counters",
                                                                                   Value = counters,
                                                                                   TypeName =
                                                                                       Data.PrepareSQL(
                                                                                           "{databaseOwner}[{objectQualifier}Findy_XsltDb_UdtCounters]")
                                                                               }
                                                                       });
                                   }).Start();
                }
            }
            return true;
        }

        public decimal getcounter(string objectCode, string counterType)
        {
            var count = Data.ExecuteSQLScalar(@"
select CurrentValue from {databaseOwner}[{objectQualifier}Findy_XsltDb_Counters]
where PortalID = @PortalID
and ObjectCode = @Code
and CounterType = @Type",
                new[]
                    {
                        new SqlParameter("@PortalID", transformer.PortalID),
                        new SqlParameter("@Code", objectCode),
                        new SqlParameter("@Type", counterType)
                    });

            return Convert.ToDecimal(count);
        }
    }
}